﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace CodeGenerator.Common
{
    /// <summary>
    /// HTML Help Workshop编译成CHM文件需要如下三个文件，分别以hhp，hhc，hhk为文件后缀名。
    ///hhp:CHM工程文件,CHM目标文件属性95%的参数都在这里被确定.
    ///hhc,列表文件,确定目标文件中左侧树形列表中"目录"选项卡下的内容.
    ///hhk,索引文件,确定目标文件中左侧树形列表中"索引"选项卡下的内容.
    ///hhp几乎就是一个标准的ini文件.分为三个小节Option,Windows,Files
    /// </summary>
    public class ChmHelper
    {
        /// <summary>
        /// CHM文件名（带后缀）
        /// </summary>
        private string ChmFileName = "鸣飞.chm1";
        /// <summary>
        /// CHM文件名
        /// </summary>
        private string ChmTitle = "";
        /// <summary>
        /// CHM默认页面
        /// </summary>
        private string DefaultPage = "";
        /// <summary>
        /// 生成文件路径
        /// </summary>
        private string SourcePath = System.Environment.CurrentDirectory;

        /// <summary>
        /// HHC 内容
        /// </summary>
        private StringBuilder hhcBody = new StringBuilder();

        /// <summary>
        /// HHP 内容
        /// </summary>
        private StringBuilder hhpBody = new StringBuilder();

        /// <summary>
        /// HHK内容
        /// </summary>
        private StringBuilder hhkBody = new StringBuilder();

        public ChmHelper()
        {

        }

        /// <summary>
        /// CHM文档生成
        /// </summary>
        /// <param name="DefaultPage">CHM默认页面</param>
        /// <param name="ChmFileName">CHM文件名(不带后缀名)</param>
        /// <param name="SourcePath">生成文件路径</param>
        public ChmHelper(string DefaultPage, string ChmFileName = "", string SourcePath = "")
        {
            this.ChmFileName = ChmFileName + ".chm";

            this.DefaultPage = DefaultPage;
            if (!String.IsNullOrEmpty(ChmFileName))
            {
                this.ChmFileName = ChmFileName;
                this.ChmTitle = ChmFileName;
            }
            else
            {
                string str = DateTime.Now.ToString("yyyyMMddHHmmss");
                this.ChmFileName = str + ".chm";
                this.ChmTitle = str;
            }
            if (!String.IsNullOrEmpty(SourcePath))
            {
                this.SourcePath = SourcePath;
            }
        }
        /// <summary>
        /// 向文本文件中写入内容
        /// </summary>
        /// <param name="filePath">文件的绝对路径</param>
        /// <param name="text">写入的内容</param>
        /// <param name="encoding">编码</param>
        private static void WriteText(string filePath, string text, Encoding encoding)
        {
            //向文件写入内容
            File.WriteAllText(filePath, text, encoding);
        }

        /// <summary>
        /// HHP 配置型文件
        /// </summary>
        /// <param name="Content"></param>
        private void CreateHHP(string Content)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("[OPTIONS]");
            sb.AppendLine("CITATION=Made by 鸣飞");
            sb.AppendLine("Compatibility=1.1 or later");
            sb.AppendLine("Compiled file=" + ChmFileName);
            sb.AppendLine("Contents file=chm.HHC");
            sb.AppendLine("COPYRIGHT=www.jschrj.com");
            sb.AppendLine("Default topic={0}");
            sb.AppendLine("Default Window=Main");
            sb.AppendLine("Display compile notes=Yes");
            sb.AppendLine("Display compile progress=Yes");
            sb.AppendLine("Full-text search=Yes");
            sb.AppendLine("Index file=chm.HHK");
            sb.AppendLine("Title={1}");
            sb.AppendLine("Enhanced decompilation=yes");
            sb.AppendLine();
            sb.AppendLine("[WINDOWS]");
            sb.AppendLine("Main=\"{1}\",\"chm.hhc\",\"chm.hhk\",\"{0}\",\"{0}\",,,,,0x63520,180,0x104E, [0,0,745,509],0x0,0x0,,,,,0");
            sb.AppendLine();
            sb.AppendLine("[MERGE FILES]");
            sb.AppendLine();
            sb.AppendLine("[FILES]");
            sb.Append(Content);    // 需要打包的文件集合

            WriteText(Path.Combine(SourcePath, "chm.hhp"), string.Format(sb.ToString(), DefaultPage, ChmTitle), Encoding.GetEncoding("gb2312"));

        }

        /// <summary>
        /// 列表文件,确定目标文件中左侧树形列表中"目录"选项卡下的内容.
        /// 
        /// Content格式：
        /// <UL>
        ///<LI>
        ///<OBJECT type="text/sitemap">
        ///<param name="Name" value="20161028112911">      // 文件名值
        ///<param name="Local" value="C:\Users\pengkai\Desktop\ConsoleApplication1\ConsoleApplication1\bin\Debug\20161028112911.chm">   // 本地文件路径
        ///<param name="ImageNumber" value="11">   // 1：根节点图标   1：叶子节点图标
        ///</OBJECT>
        ///</LI>
        ///</UL>
        /// </summary>
        /// <param name="Content"></param>
        private void CreateHHC(string Content)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">");
            sb.AppendLine("<HTML>");
            sb.AppendLine("<HEAD>");
            sb.AppendLine("<meta name=\"GENERATOR\" content=\"鸣飞 CHM文档生成\">");
            sb.AppendLine("<!-- Sitemap 1.0 -->");
            sb.AppendLine("</HEAD><BODY>");
            sb.AppendLine("<OBJECT type=\"text/site properties\">");
            sb.AppendLine("\t<param name=\"ExWindow Styles\" value=\"0x200\">");
            sb.AppendLine("\t<param name=\"Window Styles\" value=\"0x800025\">");
            sb.AppendLine("\t<param name=\"Font\" value=\"MS Sans Serif,9,0\">");
            sb.AppendLine("</OBJECT>");
            sb.Append(Content);
            sb.AppendLine("</BODY></HTML>");

            WriteText(Path.Combine(SourcePath, "chm.hhc"), sb.ToString(), Encoding.GetEncoding("gb2312"));
        }

        /// <summary>
        /// hhk,索引文件,确定目标文件中左侧树形列表中"索引"选项卡下的内容
        /// Content  数据格式同HHC
        /// </summary>
        /// <param name="Content"></param>
        private void CreateHHK(string Content)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">");
            sb.AppendLine("<HTML>");
            sb.AppendLine("<HEAD>");
            sb.AppendLine("<meta name=\"GENERATOR\" content=\"鸣飞 CHM文档生成\">");
            sb.AppendLine("<!-- Sitemap 1.0 -->");
            sb.AppendLine("</HEAD><BODY>");
            sb.AppendLine("<OBJECT type=\"text/site properties\">");
            sb.AppendLine("\t<param name=\"ExWindow Styles\" value=\"0x200\">");
            sb.AppendLine("\t<param name=\"Window Styles\" value=\"0x800025\">");
            sb.AppendLine("\t<param name=\"Font\" value=\"MS Sans Serif,9,0\">");
            sb.AppendLine("</OBJECT>");
            sb.AppendLine("<UL>");
            sb.Append(Content);
            sb.AppendLine("</UL>");
            sb.AppendLine("</BODY></HTML>");

            WriteText(Path.Combine(SourcePath, "chm.hhk"), sb.ToString(), Encoding.GetEncoding("gb2312"));
        }

        /// <summary>
        /// 拼接文件内容
        /// </summary>
        /// <param name="path">打包Path目录下的所有文件</param>
        private void Create(string path)
        {
            string[] files = Directory.GetFiles(path);
            string[] directories = Directory.GetDirectories(path);
            if (files.Length > 0 || directories.Length > 0)
            {
                hhcBody.AppendLine("\t<UL>");
            }
            string[] array = files;
            for (int i = 0; i < array.Length; i++)
            {
                string text = array[i];
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.AppendLine("\t<LI> <OBJECT type=\"text/sitemap\">");
                stringBuilder.AppendLine(string.Format("\t\t<param name=\"Name\" value=\"{0}\">", new object[]
				{
					Path.GetFileNameWithoutExtension(text)
				}));
                stringBuilder.AppendLine(string.Format("\t\t<param name=\"Local\" value=\"{0}\">", new object[]
				{
                    text
					//text.Replace(this.SourcePath, string.Empty)
				}));
                stringBuilder.AppendLine("\t\t<param name=\"ImageNumber\" value=\"11\">");
                stringBuilder.AppendLine("\t\t</OBJECT>");
                hhpBody.AppendLine(text);
                hhcBody.Append(stringBuilder.ToString());
                hhkBody.Append(stringBuilder.ToString());
            }
            string[] array2 = directories;
            int j = 0;
            while (j < array2.Length)
            {
                string text2 = array2[j];
                hhcBody.AppendLine("\t<LI> <OBJECT type=\"text/sitemap\">");
                hhcBody.AppendLine(string.Format("\t\t<param name=\"Name\" value=\"{0}\">", new object[]
				{
					Path.GetFileName(text2)
				}));
                hhcBody.AppendLine("\t\t<param name=\"ImageNumber\" value=\"1\">");
                hhcBody.AppendLine("\t\t</OBJECT>");
                Create(text2);
                j++;
            }
            if (files.Length > 0 || directories.Length > 0)
            {
                hhcBody.AppendLine("\t</UL>");
            }
        }

        /// <summary>
        /// 打包CHM文档
        /// </summary>
        /// <returns></returns>
        public bool Compile(string FilePath)
        {
            Create(FilePath);

            CreateHHC(hhcBody.ToString());
            CreateHHK(hhkBody.ToString());
            CreateHHP(DefaultPage);

            // 打包CHM文档是否成功
            bool flag = true;
            string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
            string text = folderPath + "\\HTML Help Workshop\\hhc.exe";
            if (Directory.Exists(folderPath + " (x86)"))
            {
                text = folderPath + " (x86)\\HTML Help Workshop\\hhc.exe";
            }
            Process process = new Process();

            try
            {
                ProcessStartInfo processStartInfo = new ProcessStartInfo();
                processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                processStartInfo.FileName = text;
                processStartInfo.Arguments = Path.Combine(SourcePath, "chm.hhp");
                processStartInfo.UseShellExecute = false;
                process.StartInfo = processStartInfo;
                process.Start();
                process.WaitForExit();
                if (process.ExitCode == 0)
                {
                    flag = false;
                }
            }
            catch
            {
                flag = false;
            }
            finally
            {
                process.Close();
                string[] array = new string[]
					{
						"chm.hhc", 
						"chm.hhp", 
						"chm.hhk"
					};
                string[] array2 = array;
                for (int i = 0; i < array2.Length; i++)
                {
                    string text2 = array2[i];
                    string text3 = Path.Combine(SourcePath, text2);
                    if (File.Exists(text3))
                    {
                        //File.Delete(text3);
                    }
                }
            }
            return flag;
        }

        /// <summary>
        /// 解包CHM文档
        /// </summary>
        /// <param name="filePath">chm文档绝对路径</param>
        /// <returns></returns>
        public bool DeCompile(string filePath)
        {
            string text = " -decompile " + filePath;
            Process process = Process.Start("hh.exe", text);
            process.WaitForExit();
            return true;
        }
    }
}
